﻿using System;
using System.Web.Services.Description;
using System.Xml;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection;

namespace DynamicWSInvoker
{
    public class WSInvoker
    {
        private String methodName = null;
        private String serviceName = null;
        private String wsdlUrl = null;
        private Object[] args = null;
        public WSInvoker(String wsdlUrl, String serviceName, String methodName, Object[] args)
        {
            this.wsdlUrl = wsdlUrl;
            this.serviceName = serviceName;
            this.methodName = methodName;
            this.args = args;
        }

        public Object invoke()
        {
            ServiceDescriptionImporter importer = getServiceDescriptionImporter();
            Object o = getWebServiceInstance(importer);
            Object result = getWSResult(o);

            return result;
        }

        private object getWSResult(object o)
        {
 	        Type wsType = o.GetType();
            foreach (MethodInfo m in wsType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
            {
                if (m.Name.Equals(this.methodName))
                {
                    //Console.Write("same methods...");
                }
            }
            Object result = wsType.InvokeMember(this.methodName,BindingFlags.InvokeMethod, null,o, this.args);
            return result;
                
        }

        private object getWebServiceInstance(ServiceDescriptionImporter importer)
        {
            CodeNamespace nameSpace = new CodeNamespace();
            CodeCompileUnit compileUnit = new CodeCompileUnit();
            compileUnit.Namespaces.Add(nameSpace);

            ServiceDescriptionImportWarnings warning = importer.Import(nameSpace, compileUnit);
            if(warning==0)
            {
                CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("CSharp");
                string[] assemblyReferences = new string[2] { "System.Web.Services.dll", "System.Xml.dll" };
                CompilerParameters parms = new CompilerParameters(assemblyReferences);
                CompilerResults results = codeProvider.CompileAssemblyFromDom(parms, compileUnit);
                
                foreach (CompilerError  err in results.Errors)
                {                    
                    Console.WriteLine(err.ErrorText);
                }
                

                object o = results.CompiledAssembly.CreateInstance(this.serviceName);
                return o;
            }
            return null;
        }

        private ServiceDescriptionImporter getServiceDescriptionImporter()
        {
            
            XmlTextReader xmlReader = new XmlTextReader(this.wsdlUrl);
            ServiceDescription desc = ServiceDescription.Read(xmlReader);

            ServiceDescriptionImporter importer = new ServiceDescriptionImporter();
            importer.AddServiceDescription(desc, null, null);
            importer.Style = ServiceDescriptionImportStyle.Client;
            importer.CodeGenerationOptions = System.Xml.Serialization.CodeGenerationOptions.GenerateProperties;

            return importer;
        }
    
    }
}
